package org.judo.utility.scripts;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Iterator;

import org.judo.database.JudoDBConnection;
import org.judo.database.JudoDatabaseManager;
import org.judo.database.exceptions.DatabaseConnectionException;
import org.judo.database.exceptions.DatabaseException;
import org.judo.database.exceptions.ORMException;
import org.judo.generate.CodeInjector;
import org.judo.generate.crud.CrudGenerator;
import org.judo.generate.mvc.MVCGenerator;
import org.judo.util.JavaNameConversion;
import org.judo.utility.FileDataReader;
import org.judo.utility.FileSearcher;
import org.judo.utility.SystemInReader;

public class Console
{
	
	public static void main(String[] args)
	{
		prompt();
	}
	
	protected static void options()
	{
		System.out.println("Options:");
		System.out.println("\t(1) - Create JSP View");		
		System.out.println("\t(2) - Create Controller Class and JSP View");
		System.out.println("\t(3) - Create CRUD code from Table");
		System.out.println("\t(4) - Run MVC Script");
		System.out.println("\t(5) - Delete Last Generated Java and JSP files (Undo)");
		System.out.println("\t(6) - Create Model Class From Table");
		System.out.println("\t(7) - Generate UI Elements");
		
		System.out.println();
		System.out.print("Select option number and then press enter:");
	}
	
	public static void prompt()
	{
		try
		{
			System.out.println("Judo Framework Console");
			System.out.println();
			
			while (true)
			{
				options();
				String answer = SystemInReader.getUserInput();
				
				if (answer.trim().equals("q") || answer.trim().equals("Q"))
					break;
				else if (answer.equals("1"))
					createJSP();
				else if (answer.equals("2"))
					createModelAndJSP();
				else if (answer.equals("3"))
					crud();
				else if (answer.equals("4"))
					script();
				else if (answer.equals("5"))
					undo();
				else if (answer.equals("6"))
					model();
				else if (answer.equals("7"))
					viewElements();
				else if (answer.equals(""))
				{}
				else
					System.out.println("Invalid option:"+answer);
			}	
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.out.println("Error: "+e);
			System.out.print("Press Enter to continue...");
			SystemInReader.getUserInput();
		}
	}
	
	private static void viewElements() throws Exception
	{		
		System.out.println("CRUD Options:");
		System.out.println("\t(1) - Insert Data Table");
		System.out.print("Select option number and then press enter.");
		String option = SystemInReader.getUserInput().trim();
		
		if (option.equals("1"))
		{
			generateDataTable();
		}
	}

	private static void generateDataTable() throws Exception
	{
		JudoDatabaseManager.load();
		
		HashMap tableOptions = new HashMap();
		String code = "";
		
		System.out.print("Please stop the Jetty test server if it is running.  Press enter to continue.");
		SystemInReader.getUserInput();
		
		System.out.print("Specify Database. (Press enter for 'appDB')");
		String db = SystemInReader.getUserInput();
		
		if (db.trim().equals(""))
			db = "appDB";
		
		JudoDBConnection con = null;
		ResultSet rs = null;
		Connection connection = null;
		
		try
		{
			con = JudoDatabaseManager.getConnection(db);
			connection = (Connection)con.getConnectionService();
		
			CrudGenerator gen = new CrudGenerator(connection);
			Iterator names = gen.tableNames();

			int i = 1;
			while (names.hasNext())
			{
				String tableName = (String)names.next();
				tableOptions.put(""+i,tableName);
				System.out.println("\t("+i+") - "+tableName);
				i++;
			}
			
			System.out.print("Specify Table:");
			String num = SystemInReader.getUserInput().trim();
			
			String name = (String)tableOptions.get(num);
			
			if (name == null)
			{
				System.out.println("Not a valid number: "+num);
				return;
			}
			
			FileSearcher searcher = new FileSearcher("webfiles/","###");
			String file = searcher.getFileName();
			
			if (file == null)
				System.out.println("Could not find '###' in any file to replace");
			else
			{
				code = gen.generateHTMLTable(con,name,name.toLowerCase()+"List");
				System.out.println("Generating Code in file "+file);
				CodeInjector.injectCode(file,code,"###");
			}
		}
		finally
		{
			if (connection != null)
			{
				connection.commit();
				connection.close();
			}
		}
	}

	private static void model()
		throws Exception
	{
		JudoDatabaseManager.load();
		
		HashMap tableOptions = new HashMap();
		String code = "";
		
		System.out.print("Please stop the Jetty test server if it is running.  Press enter to continue.");
		SystemInReader.getUserInput();
		
		System.out.print("Specify Database. (Press enter for 'appDB')");
		String db = SystemInReader.getUserInput();
		
		if (db.trim().equals(""))
			db = "appDB";
		
		JudoDBConnection con = null;
		ResultSet rs = null;
		Connection connection = null;
		
		try
		{
			con = JudoDatabaseManager.getConnection(db);
			connection = (Connection)con.getConnectionService();
		
			CrudGenerator gen = new CrudGenerator(connection);
			Iterator names = gen.tableNames();

			int i = 1;
			while (names.hasNext())
			{
				String tableName = (String)names.next();
				tableOptions.put(""+i,tableName);
				System.out.println("\t("+i+") - "+tableName);
				i++;
			}
			
			System.out.print("Specify Table. Press 'A' or just 'ENTER' to generate for all tables:");
			String num = SystemInReader.getUserInput().trim();
			
			System.out.print("Relative path/package: (Ex: aaa/bbb/ccc):");
			String path = SystemInReader.getUserInput().trim();
			
			if (!path.trim().equals(""))
			{
				gen.setPath(path);
			}
			
			if (num.toUpperCase().equals("A") || num.equals(""))
			{
				Iterator tableNames = gen.tableNames();

				while (tableNames.hasNext())
				{
					String tableName = (String)tableNames.next();
					code += gen.generateModelScript(tableName);
				}
			}
			else
			{
				String name = (String)tableOptions.get(num);
				
				if (name == null)
				{
					System.out.println("Not a valid number: "+num);
					return;
				}
				
				code = gen.generateModelScript(name);
			}
			
			System.out.println("CRUD Options:");
			System.out.println("\t(1) - Directly generate Java/JSP code");		
			System.out.println("\t(2) - Generate script to be editied");
			System.out.print("Select option number and then press enter.");
			String option = SystemInReader.getUserInput().trim();
			
			if (option.equals("1") || option.equals(""))
			{
				executeScript(code);
				System.out.println("Java and JSP code generated.  Please refresh your IDE.");
			}
			else if (option.equals("2"))
			{
				System.out.print("Specify file name for script.  Must have '.mvc' extension:");
				String fileName = SystemInReader.getUserInput().trim();
				writeFile(new File("script/mvc_scripts/"+fileName),code);
			}
			else
			{
				System.out.println("Invalid Option:");
			}
		}
		finally
		{
			if (connection != null)
			{
				connection.commit();
				connection.close();
			}
		}
	}

	private static void undo()
	{
		UndoMVCScript.undo();
	}

	private static void script()
	{
		MVCScript.execute();
	}
	
	private static void crud()
		throws Exception
	{
		JudoDatabaseManager.load();
		
		HashMap tableOptions = new HashMap();
		String code = "";
		
		System.out.print("Please stop the Jetty test server if it is running.  Press enter to continue.");
		SystemInReader.getUserInput();
		
		System.out.print("Specify Database. (Press enter for 'appDB')");
		String db = SystemInReader.getUserInput();
		
		if (db.trim().equals(""))
			db = "appDB";
		
		JudoDBConnection con = null;
		ResultSet rs = null;
		Connection connection = null;
		
		try
		{
			con = JudoDatabaseManager.getConnection(db);
			connection = (Connection)con.getConnectionService();
		
			CrudGenerator gen = new CrudGenerator(connection);
			Iterator names = gen.tableNames();

			int i = 1;
			while (names.hasNext())
			{
				String tableName = (String)names.next();
				tableOptions.put(""+i,tableName);
				System.out.println("\t("+i+") - "+tableName);
				i++;
			}
			
			System.out.print("Specify Table. Press 'A' or just 'ENTER' to generate for all tables:");
			String num = SystemInReader.getUserInput().trim();
			
			System.out.print("Relative path/package: (Ex: aaa/bbb/ccc):");
			String path = SystemInReader.getUserInput().trim();
			
			if (!path.trim().equals(""))
			{
				gen.setPath(path);
			}
			
			if (num.toUpperCase().equals("A") || num.equals(""))
			{
				Iterator tableNames = gen.tableNames();

				while (tableNames.hasNext())
				{
					String tableName = (String)tableNames.next();
					code += gen.generateScript(tableName);
				}
			}
			else
			{
				String name = (String)tableOptions.get(num);
				
				if (name == null)
				{
					System.out.println("Not a valid number: "+num);
					return;
				}
				
				code = gen.generateScript(name);
			}
			
			System.out.println("CRUD Options:");
			System.out.println("\t(1) - Directly generate Java/JSP code");		
			System.out.println("\t(2) - Generate script to be editied");
			System.out.print("Select option number and then press enter.");
			String option = SystemInReader.getUserInput().trim();
			
			if (option.equals("1") || option.equals(""))
			{
				executeScript(code);
				System.out.println("Java and JSP code generated.  Please refresh your IDE.");
			}
			else if (option.equals("2"))
			{
				System.out.print("Specify file name for script.  Must have '.mvc' extension:");
				String fileName = SystemInReader.getUserInput().trim();
				writeFile(new File("script/mvc_scripts/"+fileName),code);
			}
			else
			{
				System.out.println("Invalid Option:");
			}
		}
		finally
		{
			if (connection != null)
			{
				connection.commit();
				connection.close();
			}
		}
	}

	private static void createJSP() throws Exception
	{
		System.out.print("Specify JSP file name. '.jsp' at the end is optional. (Example: test_page): ");
		String jsp = SystemInReader.getUserInput();
		jsp = jsp.replace(".jsp","");
		
		String content = page();
		
		String script = "view:no_controller/"+jsp+"\n";
		script += content+"\n";
		script += "/view\n";
		
		executeScript(script);
		
		System.out.println();
		System.out.println("JSP file created.  Refresh IDE to see changes.");
		System.out.println();
	}

	private static String page()
	{		
		String content = "\th3:New Page\n";
			
		while (true)
		{
			System.out.println("Template Code generation options:");
			System.out.println("\t(1) - Include Form Skeleton Code");
			System.out.println("\t(2) - Include Datatable Skeleton Code");
			System.out.println("\t(3) - Form Wizard");
			System.out.println("\t(4) - Specify Scope");
			System.out.print("Please make a selection.  Simple press 'Enter' to select no options: ");
			String type = SystemInReader.getUserInput();
			
			//Form
			if (type.trim().equals("1"))
			{
				System.out.print("Specify form submit URL. '.do' is optional (example: calculator/add_nums):");
				String url = SystemInReader.getUserInput();
				content += "\tform:"+url.replace(".do","")+"\n";
				content += "\t\tpopulate:\n";
				content += "\t\t#example field definition:\n";
				content += "\t\t#string:thisIsAVarName,This is a caption\n";
				content += "\t/form\n";
			}
			//data table
			else if (type.trim().equals("2"))
			{
				System.out.print("What is the name of the entity that will viewed by the datatable?:");
				String name = SystemInReader.getUserInput();
				
				String queryName = name;
				
				if (!queryName.endsWith("s"))
					queryName += "s";
				
				char chs[] = queryName.toCharArray();
				
				if (Character.isUpperCase(chs[0]))
					chs[0] = Character.toLowerCase(chs[0]);
				
				queryName = new String(chs);
				
				content += "\tset_list:"+queryName+";select * from "+name+"\n";
				content += "\tdata_table:\n";
				content += "\t\titems:"+queryName+"\n";
				content += "\t\theaders:\n";
				content += "\t\t\t#header defs go here\n";
				content += "\t\t/headers\n";
				content += "\t\tvalues:\n";
				content += "\t\t\t#Column value defs go here\n";
				content += "\t\t/values\n";
				content += "\t/data_table\n";
			}
			//Form Wizard
			else if (type.trim().equals("3"))
			{
				content = formWizard(content);
			}
			//scope
			else if (type.trim().equals("4"))
			{
				System.out.println("Select a scope:");
				System.out.println("\t(1) - request");
				System.out.println("\t(2) - session");
				System.out.println("\t(3) - group");
				System.out.print("Scope Selection:");
				String scope = SystemInReader.getUserInput().trim();
				
				if (scope.equals("1"))
					content += "\tscope:request\n";
				else if (scope.equals("2"))
					content += "\tscope:session\n";
				else if (scope.equals("3"))
				{
					System.out.print("Specify group name:");
					String group = SystemInReader.getUserInput().trim();
					content += "\tscope:group,"+group+"\n";
				}
			}
			//done
			else if (type.trim().equals(""))
			{	
				break;
			}
			else
			{
				System.out.println("Invalid Response");
			}
		}
		
		return content;
	}

	private static String formWizard(String content)
	{
		System.out.print("Specify form submit URL. '.do' is optional (example: calculator/add_nums):");
		String url = SystemInReader.getUserInput();
		content += "\tform:"+url.replace(".do","")+"\n";
		content += "\t\tpopulate:\n";
		
		while (true)
		{
			System.out.println("Select Form Option:");
			System.out.println("\t(1) - Create an input field");
			System.out.println("\t(2) - Create a submit button");
			System.out.println("\t(3) - Specify forward URL");
			System.out.print("Please make a selection. To end, press enter without selecting a number: ");	
			String option = SystemInReader.getUserInput();
			
			//input
			if (option.trim().equals("1"))
			{
				System.out.print("Field Caption:");
				String caption = SystemInReader.getUserInput();
				System.out.print("Property Name:");
				String propName = SystemInReader.getUserInput();
				
				System.out.println("Select a datatype:");
				System.out.println("\t(1) - string");
				System.out.println("\t(2) - int");
				System.out.println("\t(3) - date");
				System.out.println("\t(4) - float");
				System.out.print("Please make a selection: ");
				String propType = SystemInReader.getUserInput();
				
				if (propType.trim().equals("1"))
					content += "\t\tstring:"+propName+","+caption+"\n";
				else if (propType.trim().equals("2"))
					content += "\t\tint:"+propName+","+caption+"\n";
				else if (propType.trim().equals("3"))
					content += "\t\tdate:"+propName+","+caption+"\n";
				else if (propType.trim().equals("2"))
					content += "\t\tfloat:"+propName+","+caption+"\n";
				else
				{
					System.out.println("Invalid Option.  Starting form field over.");
				}
			}
			//submit button
			else if (option.trim().equals("2"))
			{
				System.out.print("Button Caption:");
				String caption = SystemInReader.getUserInput();
				content += "\t\tsubmit:"+caption+"\n";
			}
			//Forward URL
			else if (option.trim().equals("3"))
			{
				System.out.print("URL to forward to:");
				String forwardURL = SystemInReader.getUserInput();
				content += "\t\tforward:"+forwardURL.replace(".do","")+"\n";
			}
			else if (option.trim().equals(""))
			{
				content += "\t/form\n";
				break;
			}
			else
			{
				System.out.println("Invalid Section");
			}
		}//end form options
		
		return content;
	}

	private static void createModelAndJSP() throws Exception
	{
		System.out.print("Specify Controller class name.  It will be created relative to your defined base controller package (Example: MyClass): ");
		String controller = SystemInReader.getUserInput();
		System.out.print("Specify JSP file name. '.jsp' at the end is optional. (Example: test_page): ");
		String jsp = SystemInReader.getUserInput();
		
		String url = JavaNameConversion.getUnderscoreNameFromClass(controller)+"/";
		url +=  jsp.replace(".jsp","");
			
		String script = "view:"+url+"\n";
		script += page()+"\n";
		script += "/view\n";
		
		executeScript(script);
		
		System.out.println();
		System.out.println("Controller, action method and JSP file created.  Refresh IDE to see changes.");
		System.out.println();
	}

	private static void executeScript(String script) throws Exception
	{
		System.out.println("Generated Script:\n");
		System.out.println(script);
		System.out.println("Executing...");
		MVCGenerator mvc = new MVCGenerator("mvc_code:"+script);
		mvc.parseScript();
	}

	protected static void writeFile(File file,String text)
	{
		FileWriter writer = null;
		
		try
		{
			writer = new FileWriter(file);
			writer.write(text);
			
			System.out.println("File created: "+file.getName());
		} 
		catch (Exception e)
		{
			System.out.println("Error creating File: "+file.getName()+":"+e);
			e.printStackTrace();
			return;
		}
		finally
		{
			try{writer.close();}catch(Exception e){}
		}
	}
}
